iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0
佛心分享-刷題不只是刷題

一直刷 CTF系列 第 20

一直刷 CTF - Day20

  • 分享至 

  • xImage
  •  

上課紀錄

Lab - swirl

stage 1 & 2

這兩題跟之前 Lab - phpisbest 差不多,只要在後面加上 /?A[]=[0]&B[]=[3] 就能達成各種 null==null 就能過關了

stage 3

這題我有觀察到可以 path traversal,但是我亂戳戳不到東西,過了大概十分鐘,又沒忍住點了一下 hint ,才發現要戳的東西就是寫在原始碼裡面的 config.php ,就能前往下一關了

Image

Image

stage 4

這題她沒有一個地方讀取 👀 ,但有個 extract($_POST) 可以利用 POST 的方式輸入 👀 ,之後就跟 lfi2rce 一樣,利用 php filter chain 構造出 webshell ,就能得到 Flag 了

Image

Image

Note: 這邊要注意的是這個 webshell 指令最後需要的參數 1,他是透過 $_GET[1] 來取得的,所以要寫在網址後面解析,不是寫在 POST 裡面

Lab - fakelog

他很好心的給我們看了他生成的原始碼

#!/usr/local/bin/python3
import sys

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("no argument")
        sys.exit()

    magic_num = int(sys.argv[1]) if sys.argv[1].isdigit() else sys.argv[1]
    if magic_num == 0:
        print("0 is not allowed")
        sys.exit()
    while magic_num != 1:
        with open(f"fakelog/{magic_num % 6 if isinstance(magic_num, int) else magic_num}", "r", encoding="utf-8") as fd:
            print(fd.read())
        magic_num = 3 * magic_num + 1 if magic_num % 2 else magic_num // 2

重點有兩個

  1. magic_num = int(sys.argv[1]) if sys.argv[1].isdigit() else sys.argv[1]
  2. with open(f"fakelog/{magic_num % 6 if isinstance(magic_num, int) else magic_num}", "r", encoding="utf-8") as fd:

他不會檢查 magic number 是文字,而且在他是文字的時候他還會直接讓我們讀取檔案,所以我們可以利用這個漏洞來做 path traversal

又可以從 Hint 的 dockerfile 中知道有個叫 main.py 是主程式,拿出來看看

FROM python:3.10
RUN curl -sSL https://install.python-poetry.org | POETRY_HOME=/etc/poetry python3 - 
WORKDIR /app

COPY pyproject.toml poetry.lock .
RUN /etc/poetry/bin/poetry config virtualenvs.create false && \
    /etc/poetry/bin/poetry install
COPY . .
ARG FLAG
RUN echo $FLAG > /app/flag_`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1`
USER daemon 
ENTRYPOINT ["python", "/app/main.py"]

Image

result:
from flask import Flask, render_template, request, send_file
import subprocess

app = Flask(__name__)


@app.route('/')
def home():
return render_template('home.html')


@app.route('/howtogen')
def howtogen():
return send_file('gen.py', mimetype='text/plain', as_attachment=False)


@app.route('/hint')
def hint():
return send_file('Dockerfile', mimetype='text/plain', as_attachment=False)


@app.route('/gen', methods=['GET', 'POST'])
def get_input():
message = None
if request.method == 'POST':
user_input = request.form['user_input']
if " " in user_input:
result = "evil input"
else:
result = subprocess.run(
f"python gen.py {user_input}", shell=True, capture_output=True, text=True).stdout.replace('\', '')
message = f"result: {result}"
return render_template('generate.html', message=message)


if __name__ == "__main__":
app.run(host='0.0.0.0', port=5050)

可以知道不能輸入空白,另外還有他執行程式的方法是

subprocess.run(
f"python gen.py {user_input}", shell=True, capture_output=True, text=True).stdout.replace('\', '')

可以讓我們利用類似 ;id 這樣的方式來達到 RCE,空白就用 ${IFS} 來代替,隨便戳戳看之後就能拿到 Flag 了

Image

Image

Image

參考資料


上一篇
一直刷 CTF - Day19
下一篇
一直刷 CTF - Day21
系列文
一直刷 CTF30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言